/**
 * 参考：https://cn.vitejs.dev/guide/api-plugin.html
 * 参考：https://blog.csdn.net/qq_34621851/article/details/123535975
 * 参考：https://github.com/vbenjs/vite-plugin-svg-icons
 * 参考：https://github.com/antfu/vite-plugin-restart/issues/7
 *
 * @description 在vite中使用的svg-icon插件
 * @author webxrd
 * */

import fs from 'node:fs';
import path from 'node:path';
// import * as vite from "vite";
//
//
// const mainVersion = vite.version ? (vite.version.split('.')[0]) : 2;
// console.log(mainVersion)

const create = (function () {
    /**
     * 1、获取svgInfo
     * */
    function getAllSvgFileName(dirs) {
        const svgInfo = [
            // {
            //     filename: 'D:\\a\\b\\c.svg',
            //     name: 'c'
            // }
        ];
        const svgTestReg = /\.svg$/i;
        dirs.forEach(dir => {
            fs.readdirSync(dir).forEach(name => {
                if (svgTestReg.test(name)) {
                    svgInfo.push({
                        filename: path.resolve(dir, name),
                        name: name.replace(svgTestReg, '')
                    })
                }
            })
        });
        return svgInfo;
    }

    /**
     * 2、在svgInfo基础上添加content
     * */
    function getSvgContents(svgInfo) {
        const proArr = [];
        svgInfo.forEach(function (item) {
            const pro = new Promise((resolve, reject) => {
                fs.readFile(item.filename, 'utf-8', function (err, data) {
                    if (err) {
                        throw Error(err.message);
                        // throw Error(`读取文件内容失败${item.filename}`);
                    }
                    item.content = data;
                    resolve(item);
                });
            });
            proArr.push(pro);
        });
        return Promise.all(proArr);
    }

    /**
     * 3、生成模块对应代码
     * */
    function createSvgRepository(svgContents, options) {
        const _util = (() => {
            const contentReg = /(?<=<svg[^<>]*>)([\s\S]*)(?=<\/svg>)/;
            const propReg = /(?<=<svg ?)([^<>]*)/;
            const IDReg = /id="[^"]*"/;
            const WHReg = /(width|height)="[^"]*"/g;
            return {
                /**
                 * @description 获取  "<svg>内容...</svg>"  中的  "内容..."
                 * @param { String } svgInfoItemContent svg文件内容
                 * @return { String } svgInfoItemContent中的svg标签内的所有内容
                 * */
                getSvgTagInner(svgInfoItemContent = '') {
                    return (contentReg.exec(svgInfoItemContent) || [''])[0];
                },
                /**
                 * @description 获取  "<svg ...prop>...</svg>"  中的  "...prop"
                 * @param { String } svgInfoItemContent svg文件内容
                 * @return { String } svgInfoItemContent中的svg标签 的属性 "...prop"
                 * */
                getSvgTagProp(svgInfoItemContent = '') {
                    return (propReg.exec(svgInfoItemContent) || [''])[0];
                },

                /**
                 * @description 删除字符串中的 [id="..."]
                 * @param { String } str 目标字符串
                 * @return { String } 删除 [id="..."] 后的 str
                 * */
                removeId(str = '') {
                    return str.replace(IDReg, '');
                },
                /**
                 * @description 删除字符串中的 [width="..."] 和 [height="..."]
                 * @param { String } str 目标字符串
                 * @return { String } 删除 [width="..."] 和 [height="..."] 后的 str
                 * */
                removeWH(str = '') {
                    return str.replace(WHReg, '');
                },

            };
        })();
        const symbolIdFormat = options.symbolIdFormat;
        const svgContentHtml = svgContents.map(svgInfoItem => {
            let prop = _util.getSvgTagProp(svgInfoItem.content);
            prop = _util.removeId(prop);
            prop = _util.removeWH(prop);
            prop = `id="${symbolIdFormat.replace('[name]', svgInfoItem.name)}" ${prop}`;
            const svgTagInner = _util.getSvgTagInner(svgInfoItem.content);
            return `<symbol ${prop}>${svgTagInner}</symbol>`;
        }).join('');

        const props = [
            `id="__svgIconDom__"`,
            `xmlns="http://www.w3.org/2000/svg"`,
            `xmlns:link="http://www.w3.org/1999/xlink"`,
            `style="position: fixed;top: 0; left: 0;opacity: 0;width: 0; height: 0;pointer-events: none;"`,
        ].join(' ');
        return `<svg ${props}>${svgContentHtml}</svg>`;
    }

    return async function (options) {
        const svgInfo = getAllSvgFileName(options.iconDirs);
        const svgInfoFillContents = [];
        while (svgInfo.length) {
            svgInfoFillContents.push(...await getSvgContents(svgInfo.splice(0, 5)));
        }
        const stringCode = createSvgRepository(
            svgInfoFillContents,
            options,
        );
        return {
            stringCode
        };
    }
})();

export function vitePluginSvg (options) {
    if (!options.iconDirs || !Array.isArray(options.iconDirs)) {
        throw Error("iconDirs 必须是一个由绝对路径组成的数组");
    }
    options.iconDirs.forEach(dir => {
        if (!dir || !path.isAbsolute(dir)) {
            throw Error(`期望绝对路径，但得到："${dir}"`);
        }
    });

    options = Object.assign({
        symbolIdFormat: 'icon-[name]',
    }, options);
    return {
        // 插件名称
        name: 'vite-plugin-svg',
        // 确保这个插件在其他插件之前执行
        // enforce: 'pre',
        // 将自定义内容注入HTML模板
        async transformIndexHtml(html) {
            return html.replace('</head>', `${(await create(options)).stringCode}</head>`);
        },
    }
}

